import re
from django.contrib.auth.backends import ModelBackend
from django_redis import get_redis_connection
from rest_framework import serializers
from apps.users.models import User


def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'token': token,
        'id': user.id,
        'username': user.username,
        'mobiel': user.mobile,
        'avatar': user.avatar,
    }


def get_user_by_account(account):
    """
    添加通过手机号查询用户的方法
    """
    try:
        if re.match(r'^1[356789]\d{9}$', account):  # account 是手机号
            user = User.objects.get(mobile=account)
        else:
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user


class UserByUsernameMobile(ModelBackend):
    """添加支持手机号登录"""

    def authenticate(self, request, username=None, password=None, **kwargs):
        user = get_user_by_account(username)  # username 可能是用户名也可能是手机号
        if not user.check_password(password):
            raise serializers.ValidationError('用户名或密码错误')
        return user


class UserRegSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(label='短信验证码', write_only=True)
    token = serializers.CharField(label='token', read_only=True)
    password = serializers.CharField(label='密码', write_only=True)

    class Meta:
        model = User
        fields = ['id', 'username', 'password', 'mobile', 'token', 'avatar', 'sms_code']
        extra_kwargs = {

            'password': {
                'write_only': True,
                'min_length': 6,
                'max_length': 16,
                'error_messages': {
                    'min_length': '密码为6-16个字符',
                    'max_length': '密码为6-16个字符',
                }
            },
        }

    # 判断手机号
    def validate_mobile(self, mobile):
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            raise serializers.ValidationError('手机号码格式错误')
        count = User.objects.filter(mobile=mobile).count()
        if count != 0:
            raise serializers.ValidationError('手机号已被别人使用')
        return mobile

    # 判断用户名
    def validate_username(self, username):
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            raise serializers.ValidationError('用户名格式不对')
        count = User.objects.filter(username=username).count()
        if count != 0:
            raise serializers.ValidationError('用户名已被使用')
        return username

    # 判断密码
    def validate_password(self, password):
        if not re.match(r'^[0-9A-Za-z]{6,16}$', password):
            raise serializers.ValidationError('密码长度规定在6-16位')
        return password

    # 判断用户协议是否勾选
    def validate_allow(self, allow):
        if not allow:
            raise serializers.ValidationError('请阅读后在勾选')
        return allow

    # 判断验证码
    def validate(self, attrs):
        sms_code = attrs['sms_code']
        mobile = attrs['mobile']
        redis_conn = get_redis_connection('verifications')
        redis_code = redis_conn.get('sms_%s' % mobile)
        if not redis_code:
            raise serializers.ValidationError('验证码失效')
        if sms_code != redis_code.decode():
            raise serializers.ValidationError('验证码输入有误')
        return attrs

    # 创建用户
    def create(self, validated_data):
        del validated_data['sms_code']
        user = User.objects.create_user(**validated_data)
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token
        return user
